from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.orm import Session
from jose import JWTError, jwt
from datetime import datetime, timedelta
from typing import Optional
import hashlib
from app.db import get_db
from app.models.models import Student, Admin
from app.config import settings

# 配置
SECRET_KEY = "your-secret-key-for-jwt"  # 在生产环境中应该使用环境变量
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

def get_password_hash(password: str) -> str:
    """获取密码的哈希值"""
    return hashlib.sha256(password.encode()).hexdigest()

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    """创建访问令牌"""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: Session = Depends(get_db)
) -> Student:
    """获取当前登录的用户"""
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无法验证凭据",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        print("\n=== 认证过程开始 ===")
        print(f"收到的token: {token[:20]}...")  # 只显示token的前20个字符
        
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        print(f"解码后的payload: {payload}")
        
        student_id: str = payload.get("sub")
        print(f"从token中提取的student_id: {student_id}")
        
        if student_id is None:
            print("未找到student_id，抛出认证异常")
            raise credentials_exception
            
    except JWTError as e:
        print(f"JWT解码错误: {str(e)}")
        raise credentials_exception
    
    try:
        print("\n=== 数据库查询开始 ===")
        # 检查数据库中的所有学生
        all_students = db.query(Student).all()
        print(f"数据库中的所有学生: {[(s.id, s.student_id, s.name) for s in all_students]}")
        
        # 查找特定学生
        student = db.query(Student).filter(Student.student_id == student_id).first()
        print(f"查询结果: {student}")
        
        if student is None:
            print(f"未找到学生(student_id={student_id})")
            raise HTTPException(status_code=404, detail="学生不存在")
            
        print(f"找到学生: ID={student.id}, student_id={student.student_id}, name={student.name}")
        
        # 刷新会话中的学生对象
        db.refresh(student)
        return student
        
    except Exception as e:
        print(f"数据库查询错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"数据库查询错误: {str(e)}")

async def get_current_student(
    current_user: Student = Depends(get_current_user)
):
    """验证当前用户是否为学生"""
    if not isinstance(current_user, Student):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="需要学生权限"
        )
    return current_user

async def get_current_admin(
    current_user = Depends(get_current_user)
):
    if not isinstance(current_user, Admin):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="需要管理员权限"
        )
    return current_user 